#include "StdAfx.h"
#include "ChunkIdentifier.h"
#include <iostream> 
#include <iomanip> 
#include <sstream> 

using namespace ChunkSystem;
using namespace Common;

String ChunkIdentifier::GridCoordToExternalChunkPath( const GridCoord& rCoord )
{
	char chunkIdentifierCStr[32];
	String gridChunkIdentifier;

	uint16 gridxs = uint16(rCoord.first);
	uint16 gridzs = uint16(rCoord.second);
	/*
	if (uint16(gridxs + 4096) >= 8192 || uint16(gridzs + 4096) >= 8192)
	{
		::_snprintf_s( chunkIdentifierCStr, sizeof(chunkIdentifierCStr), "%01xxxx%01xxxx/sep/",
			int(gridxs >> 12), int(gridzs >> 12) );
		gridChunkIdentifier = chunkIdentifierCStr;
	}
	if (uint16(gridxs + 256) >= 512 || uint16(gridzs + 256) >= 512)
	{
		::_snprintf_s( chunkIdentifierCStr, sizeof(chunkIdentifierCStr), "%02xxx%02xxx/sep/",
			int(gridxs >> 8), int(gridzs >> 8) );
		gridChunkIdentifier += chunkIdentifierCStr;
	}
	if (uint16(gridxs + 16) >= 32 || uint16(gridzs + 16) >= 32)
	{
		::_snprintf_s( chunkIdentifierCStr, sizeof(chunkIdentifierCStr), "%03xx%03xx/sep/",
			int(gridxs >> 4), int(gridzs >> 4) );
		gridChunkIdentifier += chunkIdentifierCStr;
	}
	*/
	::_snprintf_s( chunkIdentifierCStr, sizeof(chunkIdentifierCStr), "%04x%04xo", int(gridxs), int(gridzs) );
	gridChunkIdentifier += chunkIdentifierCStr;

	return gridChunkIdentifier;
}

class HexLookup
{
public:
	HexLookup()
	{
		for( int i = 0; i < 256; ++i )
		{
			hexLookup_[ i ] = 0;
			hexFactor_[ i ] = 0;
		}

		for (unsigned char i='0'; i<='9'; i++)
		{
			hexLookup_[i] = (uint16)(i-'0');
			hexFactor_[i] = 1;
		}

		for (unsigned char i='a'; i<='f'; i++)
		{
			hexLookup_[i] = (uint16)(i-'a' + 10);
			hexFactor_[i] = 1;
		}

		for (unsigned char i='A'; i<='F'; i++)
		{
			hexLookup_[i] = (uint16)(i-'A' + 10);
			hexFactor_[i] = 1;
		}
	};

	//done this way to avoid conditionals.
	//ascii-hex numbers directly looked up, while the factors are anded.
	//if any ascii-hex lookup is invalid, one of the factors will be 0 and thus
	//anded out, all will be invalid.
	bool fromHex( const unsigned char* f, int16& value )
	{
		value = (hexLookup_[f[3]] +
			(hexLookup_[f[2]]<<4) +
			(hexLookup_[f[1]]<<8) +
			(hexLookup_[f[0]]<<12));
		int8 factor = hexFactor_[f[0]] & hexFactor_[f[1]] & hexFactor_[f[2]] & hexFactor_[f[3]];
		return (!!factor);
	}

	uint16 hexLookup_[256];
	uint8 hexFactor_[256];
};

GridCoord ChunkIdentifier::ExternalChunkPathToGridCoord( const String& rExternalChunkId )
{
	static HexLookup hexLookup;
	int16 x = 0;
	int16 z = 0;

	//Assume name is dir/path/path/.../chunkNameo for speed
	const unsigned char* f = (const unsigned char*)rExternalChunkId.c_str();
	while ( *f ) f++;

	if( *rExternalChunkId.rbegin() == 'o' )
	{
		hexLookup.fromHex(f-9,x);
		hexLookup.fromHex(f-5,z);
	}
	
	return GridCoord(x,z);
}